#include "GlobalComponents.h"
#include "CommonFunc.h"
#include "StyleSheetSet.h"
#include "tools/cJSON.h"

#include <QGroupBox>
#include <QLabel>

AnaConfig &AnaConfig::Instance()
{
    static AnaConfig m_gConfigInstance;
    return m_gConfigInstance;
}

void AnaConfig::init()
{
    if(false == parseInitParams())
    {
        qDebug() << "[AnaConfig::init] parseInitParams faild";
    }
}

// 获取成果物保存路径
QString AnaConfig::getSavePath()
{
    return stAnaConfig.strSavePath;
}

// 设置成果物保存路径
void AnaConfig::setSavePath(const QString &strPath)
{
    stAnaConfig.strSavePath = strPath;
}

// 获取日志保存路径
QString AnaConfig::getLogPath()
{
    return stAnaConfig.strLogPath;
}

// 设置日志保存路径
void AnaConfig::setLogPath(const QString & strPath)
{
    stAnaConfig.strLogPath = strPath;
}

// 设置窗口关闭提醒
void AnaConfig::setCloseCheck(const bool bStatus)
{
    stAnaConfig.iCloseCheck = bStatus;
}

// 设置启用聊天服务端
void AnaConfig::setUseChatServer(const bool &bStatus)
{
    stAnaConfig.iUseChatServer = bStatus;
}

// 获取全局配置路径，如果路径为空，则手动选择路径，并判断是否保存适用于全局保存路径配置
QString AnaConfig::getSavePathWithAsk(QWidget *parent)
{
    QString strSavePath = stAnaConfig.strSavePath;
    if(strSavePath.isEmpty())
    {
        // 已配置路径为空，则启用窗口获取路径
        strSavePath = QFileDialog::getExistingDirectory(parent, "选择目标路径", "");   // 选择文件夹路径
        if (strSavePath.isEmpty())
        {
            QMessageBox::warning(parent, QStringLiteral("错误"), QStringLiteral("未选择文件保存路径"));
        }
        else
        {
            QMessageBox::StandardButton box;
            box = QMessageBox::question(parent, "提示", QString(" 确认路径[%1]适用于全局? ").arg(strSavePath), QMessageBox::Yes | QMessageBox::No);
            if(box == QMessageBox::Yes)
            {
                stAnaConfig.strSavePath = strSavePath;
            }
        }
    }

    return strSavePath;
}

// 获取窗口关闭状态
bool AnaConfig::getCloseCheck()
{
    return stAnaConfig.iCloseCheck;
}

// 获取聊天服务端使能状态
bool AnaConfig::getUseChatServer()
{
    return stAnaConfig.iUseChatServer;
}

// 解析配置文件参数
bool AnaConfig::parseInitParams()
{
    bool bRet = false;
    cJSON *pRoot = nullptr;

    do
    {
        stAnaConfig.init();

        std::string strContext;
        if(false == ReadFileByBinary(GLOBAL_CONFIG_FILENAME, strContext))
        {
            qDebug() << "[AnaConfig::init] parseInitParams ReadFileByBinary faild " << GLOBAL_CONFIG_FILENAME;
            break;
        }

        pRoot = cJSON_Parse(strContext.c_str());
        if(nullptr == pRoot)
        {
            qDebug() << "[AnaConfig::init] parseInitParams cJSON_Parse";
            break;
        }

        cJSON *pFontSize = cJSON_GetObjectItem(pRoot, "fontSize");
        cJSON *pLogPath = cJSON_GetObjectItem(pRoot, INIT_PARAM_LOGPATH);
        cJSON *pSavePath = cJSON_GetObjectItem(pRoot, INIT_PARAM_SAVEPATH);
        cJSON *pCloseCheck = cJSON_GetObjectItem(pRoot, INIT_PARAM_CLOSECHECK);
        cJSON *pUseChatServer = cJSON_GetObjectItem(pRoot, INIT_PARAM_USECHATSERVER);
        if(nullptr != pFontSize)
        {
            stAnaConfig.iFontSize = pFontSize->valueint;
        }

        if(nullptr != pLogPath)
        {
            stAnaConfig.strLogPath = QString::fromStdString(pLogPath->valuestring);
        }

        if(nullptr != pSavePath)
        {
            stAnaConfig.strSavePath = QString::fromStdString(pSavePath->valuestring);
        }

        if(nullptr != pCloseCheck)
        {
            stAnaConfig.iCloseCheck = pCloseCheck->valueint;
        }

        if(nullptr != pUseChatServer)
        {
            stAnaConfig.iUseChatServer = pUseChatServer->valueint;
        }

        bRet = true;
    }while(0);

    if(nullptr != pRoot)
    {
        cJSON_Delete(pRoot);
        pRoot = nullptr;
    }

    return bRet;
}

// 将配置保存到本地
bool AnaConfig::saveSetParam2File()
{
    bool bRet = false;
    cJSON *pRoot = nullptr;
    char *pRet = nullptr;
    do
    {
        pRoot = cJSON_CreateObject();
        if(nullptr == pRoot)
        {
            qDebug() << "AnaConfig::saveSetParam2File cJSON_CreateObject faild";
            break;
        }

        cJSON_AddStringToObject(pRoot, INIT_PARAM_LOGPATH, stAnaConfig.strLogPath.toStdString().c_str());
        cJSON_AddStringToObject(pRoot, INIT_PARAM_SAVEPATH, stAnaConfig.strSavePath.toStdString().c_str());
        cJSON_AddNumberToObject(pRoot, INIT_PARAM_CLOSECHECK, stAnaConfig.iCloseCheck);
        cJSON_AddNumberToObject(pRoot, INIT_PARAM_USECHATSERVER, stAnaConfig.iUseChatServer);

        pRet = cJSON_Print(pRoot);
        if(nullptr == pRet)
        {
            qDebug() << "AnaConfig::saveSetParam2File cJSON_Print faild";
            break;
        }

        // 保存配置文件到本地文件中
        std::string strContext(pRet);
        if(false == WriteBinary2File(GLOBAL_CONFIG_FILENAME, strContext))
        {
            qDebug() << "[AnaConfig::init] parseInitParams WriteBinary2File faild " << GLOBAL_CONFIG_FILENAME;
        }

        bRet = true;
    }while(0);

    if(nullptr != pRoot)
    {
        cJSON_Delete(pRoot);
        pRoot = nullptr;
    }

    if(nullptr != pRet)
    {
        free(pRet);
        pRet = nullptr;
    }

    return bRet;
}


gMsgShow &gMsgShow::Instance()
{
    static gMsgShow m_gMsgInstance;
    return m_gMsgInstance;
}

void gMsgShow::init()
{
    Qt::WindowFlags flags = Qt::Dialog;
    flags |= Qt::WindowCloseButtonHint;
    setWindowFlags(flags);
    // 去掉标题栏
    //setWindowFlags(Qt::FramelessWindowHint | windowFlags());

    // 设置大小
    setFixedSize(400, 100);
    setFont(QFont("楷体", 11));

    // 设定提示框主图标
    setWindowIcon(QIcon(":/operationIcons/resource/operationIcons/main_icon.ico"));

    QVBoxLayout *pQVBoxLayout = new QVBoxLayout(this);
    setLayout(pQVBoxLayout);

    pQVBoxLayout->setSpacing(1);
    pQVBoxLayout->setContentsMargins(5, 0, 5, 5);

    QHBoxLayout* pLayoutMsg = new QHBoxLayout;
    m_pMsgType = new QPushButton(this);
    m_pMsgType->setIcon(QIcon(QString(":/operationIcons/resource/operationIcons/information_succeed.ico")));
    m_pMsgType->setIconSize(QSize(50, 50));
    m_pMsgType->setFlat(true);

    m_pMsgLabel = new QLabel(this);
    m_pMsgLabel->setAlignment(Qt::AlignCenter); // 文本中间对齐

    pLayoutMsg->addWidget(m_pMsgType);
    pLayoutMsg->addWidget(m_pMsgLabel, Qt::AlignRight);

    QHBoxLayout* pLayoutTool = new QHBoxLayout;
    QPushButton* pDone = NewPTBWithIcon(QStringLiteral("确认"), QStringLiteral("确认输入数据"), QIcon(QString(":/operationIcons/resource/operationIcons/check_yes.ico")), this);
    connect(pDone, SIGNAL(clicked()), this, SLOT(slt_clicked_Done()));
    pDone->setMaximumWidth(80);
    pLayoutTool->addStretch();
    pLayoutTool->addWidget(pDone);

    pQVBoxLayout->addLayout(pLayoutMsg);
    pQVBoxLayout->addLayout(pLayoutTool, Qt::AlignBottom);
}

void gMsgShow::slt_clicked_Done()
{
    close();
}

void gMsgShow::insertMsg(const FORM_PROC_TYPE iType, MSG_SHOW_TYPE iMsgType, QList<QString> &listMsg)
{
    if(listMsg.empty())
    {
        return;
    }

    QString strTitle = QString("系统消息");
    switch (iType) {
    case FORM_BASE64:
        strTitle = QString("来自Base64的消息");
        break;
    case FORM_JSONTREE:
        strTitle = QString("来自JsonTree的消息");
        break;
    case FORM_CHATROOM:
        strTitle = QString("来自鱼塘的消息");
        break;
    case FORM_PICRECT:
        strTitle = QString("来自PicRect的消息");
        break;
    default:
        break;
    }

    switch (iMsgType) {
    case MSG_SHOW_INFO:
        m_pMsgType->setIcon(QIcon(QString(":/operationIcons/resource/operationIcons/information_succeed.ico")));
        break;
    case MSG_SHOW_WARN:
        m_pMsgType->setIcon(QIcon(QString(":/operationIcons/resource/operationIcons/information_warn.ico")));
        break;
    case MSG_SHOW_ERROR:
        m_pMsgType->setIcon(QIcon(QString(":/operationIcons/resource/operationIcons/information_ban.ico")));
        break;
    default:
        break;
    }

    setWindowTitle(strTitle);
    m_pMsgLabel->clear();
    QString strShow;
    uint iSize = listMsg.size() - 1;
    uint iCnt = 0;
    for(auto &it : listMsg)
    {
        iCnt++;
        strShow += it;
        strShow += (iCnt != iSize ? "" : "\n");
    }

    m_pMsgLabel->setText(strShow);  // 设置文本内容
    m_pMsgLabel->adjustSize();      // 调整控件大小
    int iShowHeight = m_pMsgLabel->height() + 50;
    iShowHeight = (iShowHeight < 100 ? 100 : iShowHeight);
    setFixedSize(m_pMsgLabel->width() + 100, iShowHeight); // 重置窗口大小
}

void myMessageBoxShow(const FORM_PROC_TYPE iType, MSG_SHOW_TYPE iMsgType, QList<QString> &listMsg, bool insertLog)
{
    gMsgShow::Instance().insertMsg(iType, iMsgType, listMsg);
    gMsgShow::Instance().exec();

    // 支持加入运行日志窗口，传入日志内容
    if(true == insertLog)
    {
        gLogShower::Instance().insertLog(iType, iMsgType, listMsg);
    }
}

void myMessageBoxShowOne(const FORM_PROC_TYPE iType, MSG_SHOW_TYPE iMsgType, QString strMsg, bool insertLog)
{
    QList<QString> listMsg;
    listMsg.push_back(strMsg);
    gMsgShow::Instance().insertMsg(iType, iMsgType, listMsg);
    gMsgShow::Instance().exec();

    // 支持加入运行日志窗口，传入日志内容
    if(true == insertLog)
    {
        gLogShower::Instance().insertLog(iType, iMsgType, listMsg);
    }
}

// 设置窗口单例对象
gSetDialog &gSetDialog::Instance()
{
    static gSetDialog m_gSetInstance;
    return m_gSetInstance;
}

// 初始化界面
void gSetDialog::init()
{
    // 去掉窗口的问号
    Qt::WindowFlags flags = Qt::Dialog;
    flags |= Qt::WindowCloseButtonHint;
    setWindowFlags(flags);

    // 窗口无边框配置
    //setWindowFlags(Qt::Dialog | Qt::FramelessWindowHint);

    // 设定提示框主图标
    setWindowIcon(QIcon(":/operationIcons/resource/operationIcons/main_icon.ico"));
    setWindowTitle(QStringLiteral("全局参数设置"));
    setFont(gstFont);

    QVBoxLayout *pQVBoxLayout = new QVBoxLayout(this);
    setLayout(pQVBoxLayout);

    // 路径设置
    QGroupBox *pBoxPath = new QGroupBox(this);
    pBoxPath->setFont(gstFont);
    pBoxPath->setTitle(QStringLiteral("路径配置"));
    QGridLayout *pPathLayout = new QGridLayout;
    pBoxPath->setLayout(pPathLayout);

    // 成果物保存路径
    m_pSavePath = new QLineEdit(this);
    m_pSavePath->setAlignment(Qt::AlignCenter);
    QLabel *pLabel = new QLabel(QStringLiteral("保存路径"));
    QPushButton *pOpenSavePath = new QPushButton(this);
    pOpenSavePath->setText(QString("浏览"));
    connect(pOpenSavePath, SIGNAL(clicked()), this, SLOT(slt_readSavePath()));
    pPathLayout->addWidget(pLabel, 0, 0);
    pPathLayout->addWidget(m_pSavePath, 0, 1);
    pPathLayout->addWidget(pOpenSavePath, 0, 2);

    // 日志路径保存路径
    m_pLogPath = new QLineEdit(this);
    m_pLogPath->setAlignment(Qt::AlignCenter);
    QLabel *pLabelLog = new QLabel(QStringLiteral("日志路径"));
    QPushButton *pOpenLogPath = new QPushButton(this);
    pOpenLogPath->setText(QStringLiteral("浏览"));
    connect(pOpenLogPath, SIGNAL(clicked()), this, SLOT(slt_readLogPath()));
    pPathLayout->addWidget(pLabelLog, 1, 0);
    pPathLayout->addWidget(m_pLogPath, 1, 1);
    pPathLayout->addWidget(pOpenLogPath, 1, 2);

    // 通用设置
    QGroupBox *pBoxParam = new QGroupBox(this);
    pBoxParam->setFont(gstFont);
    pBoxParam->setTitle(QString("通用设置"));
    QGridLayout *pLayoutParam = new QGridLayout;
    pBoxParam->setLayout(pLayoutParam);

    m_pCloseCheck = new MyCheckBox(this);
    m_pCloseCheck->setText(QStringLiteral("【关闭确认】"));
    m_pCloseCheck->setFlat(true);
    QLabel *pLabelCloseCheckTips = new QLabel(QString("选中使能，则子标签页关闭时将发出提示确认"));
    pLayoutParam->addWidget(m_pCloseCheck, 0, 0, Qt::AlignLeft);
    pLayoutParam->addWidget(pLabelCloseCheckTips, 0, 1);

    m_pUseChatServer = new MyCheckBox(this);
    m_pUseChatServer->setText(QStringLiteral("【聊天服务端】"));
    m_pUseChatServer->setFlat(true);
    QLabel *pLabelUseChatServerTips = new QLabel(QString("选中使能，则首页将启用聊天服务端功能"));
    pLayoutParam->addWidget(m_pUseChatServer, 1, 0, Qt::AlignLeft);
    pLayoutParam->addWidget(pLabelUseChatServerTips, 1, 1);

    QHBoxLayout* pLayoutTool = new QHBoxLayout;
    QPushButton* pDone = NewPTBWithIcon(QStringLiteral("确认"), QStringLiteral("保存设置并关闭窗口"), QIcon(QString(":/operationIcons/resource/operationIcons/check_yes.ico")), this);
    QPushButton* pCancel = NewPTBWithIcon(QStringLiteral("取消"), QStringLiteral("取消配置"), QIcon(QString(":/operationIcons/resource/operationIcons/close.ico")), this);
    connect(pDone, SIGNAL(clicked()), this, SLOT(slt_clickedDone()));
    connect(pCancel, SIGNAL(clicked()), this, SLOT(slt_clickedCancel()));
    pDone->setMaximumWidth(80);
    pCancel->setMaximumWidth(80);
    pLayoutTool->addStretch();
    pLayoutTool->addWidget(pCancel);
    pLayoutTool->addWidget(pDone);

    // 添加控件到窗口
    pQVBoxLayout->addWidget(pBoxPath);
    pQVBoxLayout->addWidget(pBoxParam);
    pQVBoxLayout->addLayout(pLayoutTool, Qt::AlignBottom);

    // 根据控件情况调整窗口大小
    pBoxPath->adjustSize();
    pBoxParam->adjustSize();

    int iAdjustHeight = pBoxPath->height() + pBoxParam->height() + 70;
    setFixedSize(600, iAdjustHeight);
}

// 更新参数，从全局参数中获取并展示
void gSetDialog::updateParams()
{
    QString strSavePath = AnaConfig::Instance().getSavePath();
    if(!strSavePath.isEmpty())
    {
        m_pSavePath->setText(strSavePath);
    }

    QString strLogPath = AnaConfig::Instance().getLogPath();
    if(!strLogPath.isEmpty())
    {
        m_pLogPath->setText(strLogPath);
    }

    m_pCloseCheck->setStatus(AnaConfig::Instance().getCloseCheck());
    m_pUseChatServer->setStatus(AnaConfig::Instance().getUseChatServer());
}

// 确认按钮功能:配置内容同步到全局后关闭窗口
void gSetDialog::slt_clickedDone()
{
    saveSetParam();
    close();
}

void gSetDialog::slt_clickedCancel()
{
    close();
}

void gSetDialog::slt_clickedSync()
{
    saveSetParam();
}

// 获取成果物保存路径
void gSetDialog::slt_readSavePath()
{
    QString strSavePath = QFileDialog::getExistingDirectory(nullptr, "选择目标路径", "");   // 选择文件夹路径
    if (strSavePath.isEmpty())
    {
        myMessageBoxShowOne(FORM_NULL, MSG_SHOW_ERROR, QStringLiteral("未选择文件保存路径"));
    }
    else
    {
        m_strSavePath = strSavePath;            // 保存当前选择路径
        m_pSavePath->clear();
        m_pSavePath->setText(m_strSavePath);    // 显示路径
    }
}

// 获取日志保存路径
void gSetDialog::slt_readLogPath()
{
    QString strLogPath = QFileDialog::getExistingDirectory(nullptr, "选择目标路径", "");   // 选择文件夹路径
    if (strLogPath.isEmpty())
    {
        myMessageBoxShowOne(FORM_NULL, MSG_SHOW_ERROR, QStringLiteral("未选择文件保存路径"));
    }
    else
    {
        m_strLogPath = strLogPath;            // 保存当前选择路径
        m_pLogPath->clear();
        m_pLogPath->setText(m_strLogPath);    // 显示路径
    }
}

void gSetDialog::saveSetParam()
{
    // 更新全局参数配置内容
    QString strSavePath = m_pSavePath->text();
    QString strLogPath = m_pLogPath->text();
    if(!strSavePath.isEmpty())
    {
        AnaConfig::Instance().setSavePath(strSavePath);
    }

    if(!strLogPath.isEmpty())
    {
        AnaConfig::Instance().setLogPath(strLogPath);
    }

    AnaConfig::Instance().setCloseCheck(m_pCloseCheck->getStatus());
    AnaConfig::Instance().setUseChatServer(m_pUseChatServer->getStatus());

    // 更新本地配置文件
    if(false == AnaConfig::Instance().saveSetParam2File())
    {
        myMessageBoxShowOne(FORM_NULL, MSG_SHOW_ERROR, QStringLiteral("配置参数保存到本地配置文件失败，请重试!"));
    }
}

// 设置窗口单例对象
gLogShower &gLogShower::Instance()
{
    static gLogShower m_gLogShower;
    return m_gLogShower;
}

// 初始化界面
void gLogShower::init()
{
    // 去掉窗口的问号
    Qt::WindowFlags flags = Qt::Dialog;
    flags |= Qt::WindowCloseButtonHint;
    setWindowFlags(flags);

    // 设定提示框主图标
    setWindowIcon(QIcon(":/operationIcons/resource/operationIcons/main_icon.ico"));
    setWindowTitle(QStringLiteral("运行日志"));
    setFont(gstFont);

    setFixedSize(350, 600);

    QVBoxLayout *pLayout = new QVBoxLayout(this);
    setLayout(pLayout);
    pLayout->setContentsMargins(1, 1, 1, 1);

    m_pLogShower = new QTextBrowser(this);
    pLayout->addWidget(m_pLogShower);

    QHBoxLayout *pLayoutFunc = new QHBoxLayout;
    QPushButton *pBtn = new QPushButton(this);
    pBtn->setMinimumWidth(50);
    pBtn->setFont(gstFont);
    pBtn->setText(QString("清空"));

    pLayoutFunc->addStretch();
    pLayoutFunc->addWidget(pBtn);
    pLayout->addLayout(pLayoutFunc);
}

// 更新参数，从全局参数中获取并展示
void gLogShower::insertLog(const FORM_PROC_TYPE iType, MSG_SHOW_TYPE iMsgType, QList<QString> &listMsg)
{
    if(listMsg.isEmpty())
    {
        return;
    }

    QString strTitle = QString("系统消息");
    // 根据子标签页类型选择待显示类型
    switch (iType) {
    case FORM_BASE64:
        strTitle = QString("来自Base64的消息");
        break;
    case FORM_JSONTREE:
        strTitle = QString("来自JsonTree的消息");
        break;
    case FORM_CHATROOM:
        strTitle = QString("来自鱼塘的消息");
        break;
    case FORM_PICRECT:
        strTitle = QString("来自PicRect的消息");
        break;
    default:
        break;
    }

    // 根据消息类型选择图标
    switch (iMsgType) {
    case MSG_SHOW_INFO:
        //m_pMsgType->setIcon(QIcon(QString(":/operationIcons/resource/operationIcons/information_succeed.ico")));
        break;
    case MSG_SHOW_WARN:
        //m_pMsgType->setIcon(QIcon(QString(":/operationIcons/resource/operationIcons/information_warn.ico")));
        break;
    case MSG_SHOW_ERROR:
        //m_pMsgType->setIcon(QIcon(QString(":/operationIcons/resource/operationIcons/information_ban.ico")));
        break;
    default:
        break;
    }

}

// 清理已有展示内容
void gLogShower::slt_Clear()
{
    m_pLogShower->clear();
}
